/**
 * Copyright (c) 2011, RealPaaS Technologies Ltd. All rights reserved.
 */
package com.cat.common.util;

import java.util.HashMap;
import java.util.Map;

public final class Base36 {

    private static final char[] ID_TABLE = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

    private static final int RADIX = ID_TABLE.length;

    private static final Map<Character, Integer> ID_MAP = new HashMap<Character, Integer>(100);

    static {
        for (int i = 0; i < RADIX; i++) {
            ID_MAP.put(Character.valueOf(ID_TABLE[i]), Integer.valueOf(i));
        }
    }

    private Base36() {
    }

    public static String encode(long id) {
        StringBuilder sb = new StringBuilder(10);
        int rest = -1;

        while (id > 0) {
            rest = (int) (id % RADIX);
            id = id / RADIX;
            sb.insert(0, ID_TABLE[rest]);
        }

        if (-1 == rest && 0 == id) {
            sb.append(ID_TABLE[0]);
        } else if (-1 == rest && 0 < id) {
            throw new IllegalArgumentException("\"id\" should not be negative");
        }

        return sb.toString();
    }

    public static long decode(String code) {
        if (code == null || code.length() == 0) {
            throw new IllegalArgumentException("Base36 code is needed as the only argument");
        }

        long id = 0;
        int position = 0;
        long radix = 1;
        for (int i = code.length() - 1; i > -1; i--, position++) {
            Character ch = Character.valueOf(code.charAt(i));
            Integer num = ID_MAP.get(ch);
            if (num == null) {
                throw new IllegalArgumentException(code + " is not legal Base36 code");
            }
            if (position != 0) {
                radix = radix * RADIX;
            }
            id += radix * num.longValue();
        }

        return id;
    }

    public static boolean isBase36(String code) {
        if (code == null || code.length() == 0) {
            return false;
        }
        int len = code.length();
        for (int i = 0; i < len; i++) {
            Character ch = Character.valueOf(code.charAt(i));
            if (!ID_MAP.containsKey(ch)) {
                return false;
            }
        }
        return true;
    }

}
